use tonic::Request;
use tonic::transport::Channel;
use futures::stream;
// use std::fmt::Result; // This import is not needed and causes a conflict

use myproto::my_rpc_client::MyRpcClient;
use myproto::{Key, KvPair, Value, RequestState};
use anyhow::Result;

pub mod myproto {
    include!("pb/myproto.rs");
}

async fn get_kv_list(client: &mut MyRpcClient<Channel>) -> Result<(),Box<dyn std::error::Error>>{
    let rqs = RequestState{
        request_info: "get_kv_list".into()
    };

    let mut stream = client.get_kv_list(Request::new(rqs)).await?.into_inner();

    while let Some(kv_paire) = stream.message().await?{
        println!("Received {:?}", kv_paire);
    }
    Ok(())
}

async fn run_set_kv_list(client: &mut MyRpcClient<Channel>) -> Result<(),Box<dyn std::error::Error>> {

    let mut pairs = vec![];
    
    for i in 0..3 {
    pairs.push(KvPair{
        key: Some(Key{
            key: i.to_string()
        }),
        val: Some(Value{
            val: i.to_string()
        })
    });       

    println!("Sending {:?}", pairs);

    let request = Request::new(stream::iter(pairs.clone()));

    match client.set_kv_list(request).await {
        Ok(res) => {
            println!("Response: {:?}", res);
        }
        Err(e) => {
            println!("Error: {:?}", e);
        }
    }
}
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(),Box<dyn std::error::Error>> {
    let mut client = MyRpcClient::connect("http://[::1]:10000").await?;
    println!("*** SIMPLE RPC ***");

    let res0 = client.set_kv(Request::new(
        KvPair{
            key: Some(Key{key: "key0".into()}),
            val: Some(Value{val: "val0".into()})
        }
    )).await?;

    println!("Response: {:?}", res0);

    let res1 = client.get_kv(Request::new(
        Key{key: "key0".into()},
    )).await?;

    println!("Response: {:?}", res1);

    println!("\n*** CLIENT STREAMING ***");
    run_set_kv_list(&mut client).await?;

    println!("\n*** SERVER STREAMING ***");
    get_kv_list(&mut client).await?;
    
    Ok(())


}

